<template>
  <div class="reply-item flex overflow-hidden">
    <!-- 左侧头像 -->
    <div class="left-avatar mr-2" style="">
      <UserAvatar
        :image-url="replyItem.UserAvatar"
        :data-user-id="replyItem.UserID"
        class="cursor-pointer"
        size="small"
        @mouseenter="onEnter"
        @mouseleave="onLeave"
      />
    </div>

    <div class="right-main flex-1 flex flex-col overflow-hidden">
      <!-- 回复顶部信息 -->
      <div
        class="flex justify-between teld-color-gray"
        :class="[dense || true ? 'mb-1' : 'mb-2']"
      >
        <div class="flex items-center">
          <span class="teld-color-gray font-semibold">
            {{ userNameDisplay }}
          </span>
          <SvgTriangle
            v-if="replyItem.RespondedUserID"
            width="8"
            height="8"
            class="mx-2"
          />
          <span
            v-if="replyItem.RespondedUserID"
            class="teld-color-gray font-semibold"
          >
            {{ replyItem.RespondedUserName }}
          </span>
        </div>
        <!-- <span :title="replyItem.ReplyTime" class="teld-color-gray">{{ replyItem.ReplyTimeRelative }}</span> -->
      </div>

      <!-- 回复内容行 -->
      <div
        class="reply-content break-all"
        :class="[dense || true ? 'mb-1' : 'mb-2']"
      >
        <div
          ref="replyContentRef"
          v-if="!replyItem.IsDeleted"
          v-html="decodeURIComponent(replyItem.Content)"
          @click="onClickContent"
        ></div>
        <div v-else class="teld-color-gray">
          {{ /*该条评论回复已删除*/ qLangComment.replyIsDeleted }}
        </div>
      </div>

      <!-- 附件 -->
      <section
        v-if="!replyItem.IsDeleted && replyItem.Attachments.length"
        class="attachments-section w-full"
        :class="[dense ? 'mb-1' : 'mb-2']"
      >
        <div
          v-for="attachment in replyItem.Attachments"
          :key="attachment.ID"
          class="attachment-file flex items-center hover:text-theme-color cursor-pointer"
          :class="[dense ? '' : 'py-1']"
          @click="onClickAttachment(attachment)"
        >
          <!-- 文件类型图标 -->
          <FileTypeIcon :file-name="attachment.FileName" class="w-5 h-5 mr-2" />
          <!-- 文件名 -->
          <div
            class="flex-1 truncate overflow-hidden"
            :title="attachment.FileName"
          >
            {{ attachment.FileName }}
          </div>
        </div>
      </section>

      <!-- 回复底部按钮行 -->
      <div class="flex justify-between">
        <!-- 相对时间 -->
        <span :title="replyItem.ReplyTime" class="teld-color-gray">
          {{ replyItem.ReplyTimeRelative }}
        </span>
        <div
          class="reply-operations flex justify-end"
          :class="[disabled ? 'teld-color-lightgray' : 'teld-color-gray']"
        >
          <!-- TODO 各点击按钮是否加 Tab 导航 :tabindex="disabled ? -1 : 0" outline-on-focus -->
          <!-- 点赞 -->
          <div
            class="reply-like flex outline-on-focus rounded-sm leading-5 hover:text-theme-color"
            :class="[disabled ? 'cursor-not-allowed' : 'cursor-pointer']"
            @click="onClickLike"
          >
            <SvgHeartFilled v-show="replyItem.Liked" class="mr-1" />
            <SvgHeart v-show="!replyItem.Liked" class="mr-1" />
            <span class="">{{ replyItem.LikeCount || 0 }}</span>
          </div>
          <!-- 收藏 -->
          <div
            class="reply-star flex ml-2 outline-on-focus rounded-sm leading-5 hover:text-theme-color hidden"
            :class="[disabled ? 'cursor-not-allowed' : 'cursor-pointer']"
            @click="onClickFavorite"
          >
            <SvgStarFilled v-show="replyItem.IsFavorite" class="mr-1" />
            <SvgStar v-show="!replyItem.IsFavorite" class="mr-1" />
            <span class="">
              {{ replyItem.FavoriteCount || 0 }}
            </span>
          </div>
          <!-- 回复 -->
          <div
            class="reply-reply ml-2 outline-on-focus rounded-sm hover:text-theme-color"
            :class="[
              disabled ? 'cursor-not-allowed' : 'cursor-pointer',
              inputVisible
                ? 'teld-theme-color'
                : disabled
                  ? 'teld-color-lightgray'
                  : 'teld-color-gray',
            ]"
            @click="onClickReply"
          >
            {{ inputVisible ? qLangComment.cancelReply : qLangComment.reply }}
          </div>
          <!-- 删除 -->
          <div
            v-if="replyItem.CanCancel && !disabled"
            class="reply-revoke ml-2 outline-on-focus rounded-sm hover:text-theme-color"
            :class="[disabled ? 'cursor-not-allowed' : 'cursor-pointer']"
          >
            {{ /*删除*/ qLangComment.delete }}
            <t-popup-proxy :target="!disabled" v-model="deleteConfirmVisible">
              <div
                class="popover-content p-4 bg-white teld-color-black text-sm"
                style="min-width: 180px; max-width: 280px"
              >
                <div class="mb-2">
                  {{ /*确定要删除吗？*/ qLangComment.deleteConfirmation }}
                </div>
                <div class="flex justify-end">
                  <span class="mr-2 cursor-pointer" @click="hideConfirm">
                    {{ /*取消*/ qLangComment.confirmNo }}
                  </span>
                  <span
                    class="teld-theme-color cursor-pointer"
                    @click="onClickRevoke"
                  >
                    {{ /*确定*/ qLangComment.confirmYes }}
                  </span>
                </div>
              </div>
            </t-popup-proxy>
          </div>
        </div>
      </div>

      <!-- 评论的回复框 -->
      <draft-editor
        ref="draftEditorRef"
        :visible="inputVisible"
        :placeholder="inputPlaceholder"
        class="w-full transition-all duration-300 overflow-hidden"
        :class="[inputVisible ? (dense ? 'my-1' : 'my-2') : 'h-0']"
        @comment="onReplyToReply"
      />
    </div>

    <!-- 图片预览 -->
    <t-image-preview
      ref="imagePreviewRef"
      v-model="currentImgSrc"
      :src-list="previewSrcList"
    ></t-image-preview>
  </div>
</template>

<script>
// Components
import SvgHeart from '../../components/svg-icons/heart.vue';
import SvgHeartFilled from '../../components/svg-icons/heart-filled.vue';
import SvgStar from '../../components/svg-icons/star.vue';
import SvgStarFilled from '../../components/svg-icons/star-filled.vue';
import SvgTriangle from '../../components/svg-icons/triangle.vue';
import UserAvatar from '../../components/user-avatar/index.vue';
import FileTypeIcon from '../../components/file-type-icon/index.vue';
import DraftEditor from '../draft-editor/index.vue';

// Utils
import { useRelativeTime, saveAs } from '../../hooks';
import { MENTIONED_USER_CLASS_NAME } from '../../utils';
import dayjs from 'dayjs';
import {
  saveReply,
  deleteReply,
  turnOnLike,
  cancelLike,
} from '../../hooks/api.js';

export default {
  name: 'ReplyItem',
  inject: [
    'qLangComment',
    'dense',
    'loginUserInfo',
    'showPersonnelInfo',
    'hidePersonnelInfo',
    'notificationLink',
  ],
  props: {
    /**
     * Reply数据条目
     */
    dataItem: {
      type: Object,
      default: () => {},
    },
    isCommentDeleted: {
      type: Boolean,
      default: false,
    },
  },
  components: {
    SvgHeart,
    SvgHeartFilled,
    SvgStar,
    SvgStarFilled,
    SvgTriangle,
    DraftEditor,
    // RevokePopover,
    UserAvatar,
    FileTypeIcon,
  },
  data() {
    return {
      // isLoading: true,
      inputVisible: false,
      replyItem: {},
      revokeConfirmVisible: false,
      previewSrcList: [],
      currentImgSrc: null,
      deleteConfirmVisible: false,
    };
  },
  computed: {
    disabled() {
      return this.isCommentDeleted || this.replyItem.IsDeleted;
    },
    showReplyTo() {
      // TODO
      return true;
    },
    isAuthor() {
      const loginUser = this.loginUserInfo;
      return loginUser.userId === this.replyItem.UserID;
    },
    userNameDisplay() {
      return this.isAuthor ? this.qLangComment.me : this.replyItem.UserName;
    },
    inputPlaceholder() {
      return `${this.qLangComment.reply} ${this.userNameDisplay}`;
    },
  },
  created() {
    const { ReplyTime } = this.dataItem;
    const timeRelative = useRelativeTime(this.$q.lang.relativeTime)(ReplyTime);
    this.replyItem = {
      ...this.dataItem,
      ReplyTime: dayjs(ReplyTime).format('YYYY/MM/DD HH:mm:ss'),
      ReplyTimeRelative: timeRelative || '',
    };
  },
  mounted() {
    this.$nextTick(() => {
      this.initImagePreview();
      this.initPersonnelInfo();
    });
  },
  methods: {
    initImagePreview() {
      const elImages = this.$el.querySelectorAll('.reply-content img');
      this.previewSrcList = [].map.call(elImages, elImage => {
        return elImage.src;
      });
    },
    initPersonnelInfo() {
      const replyContentRef = this.$refs.replyContentRef;
      if (!replyContentRef) return;
      const elMentionedUsers = replyContentRef.querySelectorAll(
        `.${MENTIONED_USER_CLASS_NAME}`,
      );
      elMentionedUsers.forEach(el => {
        el.addEventListener('mouseenter', this.onEnter);
        el.addEventListener('mouseleave', this.onLeave);
      });
      console.log(`initPersonnelInfo`, elMentionedUsers);
    },
    onEnter(e) {
      this.showPersonnelInfo({ target: e.target });
    },
    onLeave() {
      this.hidePersonnelInfo();
    },
    async onClickLike() {
      if (this.disabled) return;
      const isLike = (this.replyItem.Liked = !this.replyItem.Liked);
      const diff = this.replyItem.Liked ? 1 : -1;
      this.replyItem.LikeCount += diff;
      let succeeded = false;

      const payload = isLike
        ? { CommentID: this.replyItem.CommentID, TargetID: this.replyItem.ID }
        : { Id: this.replyItem.CommentID, TargetID: this.replyItem.ID };
      // const serviceCode = isLike ? 'CMTS-Like' : 'CMTS-CancelLike';
      const updateLikeState = isLike ? turnOnLike : cancelLike;
      try {
        // const { data } = await this.$utils.sgApi.getDataAsync({
        //   url: this.$utils.common.getServiceUrl(serviceCode),
        //   data: isLike
        //     ? { comment: JSON.stringify(payload) }
        //     : { input: JSON.stringify(payload) },
        // });
        const res = await updateLikeState(payload);

        if (!res || res.state !== '1') {
          return;
        }

        succeeded = true;
        // this.$TP.$message.success(isLike ? '已点赞' : '已取消点赞');
      } catch (error) {
        console.log(error);
      } finally {
        // 接口调用失败后，页面状态回滚
        if (!succeeded) {
          this.replyItem.Liked = !isLike;
          this.replyItem.LikeCount -= diff;
        }
      }
    },
    async onClickFavorite() {
      if (this.disabled) return;
      this.replyItem.IsFavorite = !this.replyItem.IsFavorite;
      const diff = this.replyItem.IsFavorite ? 1 : -1;
      this.replyItem.FavoriteCount += diff;
    },
    onClickReply() {
      if (this.disabled) return;
      this.inputVisible = !this.inputVisible;
    },
    /** 使用 tp-popover 时，用于隐藏弹出的气泡 */
    hideConfirm() {
      // document.body.click();
      this.deleteConfirmVisible = false;
    },
    /** TODO 使用自定义的RevokeConfirm组件时用 */
    toggleRevokeConfirm() {
      this.revokeConfirmVisible = !this.revokeConfirmVisible;
    },
    async onClickRevoke() {
      if (this.disabled) return;
      this.hideConfirm();
      this.inputVisible = false;
      this.replyItem.IsDeleted = true;

      try {
        // const { data } = await this.$utils.sgApi.getDataAsync({
        //   url: this.$utils.common.getServiceUrl('CMTS-CancelReply'), //+ `&id=${this.comment.ID}`,
        //   // method: 'GET',
        //   data: { id: this.replyItem.ID },
        // });
        const res = await deleteReply(this.replyItem.ID);
        if (!res || res.state !== '1') {
          this.replyItem.IsDeleted = false;
          this.replyItem.CanCancel = false;
          // this.$TP.$message.error(data.errmsg);
          this.$q.notify({
            message: `${res.errmsg}`,
            // icon: '',
            type: 'negative',
            textColor: 'white',
            position: 'top',
            timeout: 1000,
            attrs: {
              // 为通知的 DOM 本身设置属性:
              'comment-notification': 'negative', // 这是为了做精准选择器调样式用的
            },
          });
          return;
        }

        // this.$TP.$message.success('已删除');
        this.$q.notify({
          // message: `已删除`,
          message: this.qLangComment.deleteDone,
          // icon: '',
          type: 'positive',
          textColor: 'white',
          position: 'top',
          timeout: 1000,
          attrs: {
            // 为通知的 DOM 本身设置属性:
            'comment-notification': 'positive', // 这是为了做精准选择器调样式用的
          },
        });
        this.$emit('delete', this.replyItem);
      } catch (error) {
        this.replyItem.IsDeleted = false;
        this.replyItem.CanCancel = false;
        // this.$TP.$message.error('删除失败');
        this.$q.notify({
          // message: `删除失败`,
          message: this.qLangComment.deleteFailed,
          // icon: '',
          type: 'negative',
          textColor: 'white',
          position: 'top',
          timeout: 1000,
          attrs: {
            // 为通知的 DOM 本身设置属性:
            'comment-notification': 'negative', // 这是为了做精准选择器调样式用的
          },
        });
        console.log(error);
      }
    },
    async onReplyToReply(draftInfo) {
      const loginUser = this.loginUserInfo;
      const { content, fileList, userIdList, onSucceed, onFail } = draftInfo;
      const newCommentReply = {
        // 接口必传字段：
        CommentID: this.replyItem.CommentID,
        Content: content,
        UserAvatar: loginUser.avatar,
        // RespondedUserID: this.replyItem.UserID,
        // RespondedUserName: this.replyItem.UserName,
        TargetID: this.replyItem.ID,
        Attachments: fileList.map(n => n.result),
        MentionedUsers: JSON.stringify(userIdList),
        Url: this.notificationLink(),
        UrlParams: JSON.stringify({
          // fpath: encodeURIComponent(this.pageUrl),
          showComment: true,
          commentId: this.replyItem.CommentID,
        }),
      };
      // 回复给
      if (loginUser.userId !== this.replyItem.UserID) {
        newCommentReply.RespondedUserID = this.replyItem.UserID;
        newCommentReply.RespondedUserName = this.replyItem.UserName;
      }

      try {
        const res = await saveReply(newCommentReply);
        console.log('SaveReply', res);
        if (!res || res.state !== '1' || !res.data) {
          onFail();
          return;
        }

        // mock new record, and override with real data
        Object.assign(
          newCommentReply,
          {
            ID: 'comment-reply-m-' + parseInt(Math.random() * 1000),
            ReplyTime: Date().toLocaleString(),
            UserID: loginUser.userId,
            UserName: loginUser.userName,
            Liked: false,
            LikeCount: 0,
            IsFavorite: false,
            FavoriteCount: 0,
            IsDeleted: false,
            CanCancel: true,
          },
          res.data,
        );

        // 调接口成功后清空输入框内容
        onSucceed();
        this.inputVisible = false;
        // 评论完将新添加评论展示出来
        this.$emit('reply', newCommentReply);
      } catch (error) {
        console.log(error);
        onFail();
      }
    },
    onImageLoad(e) {
      e.target.click();
    },
    onClickContent(e) {
      const el = e.target;
      if (el.nodeName === 'IMG' && el.currentSrc) {
        this.currentImgSrc = el.currentSrc;
      }
    },
    handleDownloadFile(attachment) {
      const { AttachmentUrl, FileName } = attachment;
      saveAs({
        url: AttachmentUrl,
        fileName: FileName,
      });
    },
    onClickAttachment(attachment) {
      const ext = attachment.FileName.split('.').pop().toLowerCase();
      const previwer = this.$refs.imagePreviewRef;
      if (['png', 'jpg', 'jpeg', 'gif'].includes(ext) && previwer) {
        previwer.open(attachment.AttachmentUrl);
        return;
      }
      this.handleDownloadFile(attachment);
    },
  },
};
</script>

<style lang="scss" scoped></style>
